package utils

import (
	"fmt"
	"math/rand"
	"sync"
	"time"

	log "github.com/sirupsen/logrus"
)

const (
	StartTime              int64 = 1622044800000
	WorkerIdBits           int64 = 10
	SequenceBits           int64 = 12
	IdShiftBits            int64 = SequenceBits
	TimestampLeftShiftBits int64 = IdShiftBits + WorkerIdBits
	SequenceMask           int64 = ^(-1 << SequenceBits)
	MaxId                  int64 = ^(-1 << WorkerIdBits)
)

type RoomIdCreate struct {
	LastTimestamp int64
	Sequence      int64
	WorkerId      int64
	sync.Mutex
}

func NewRoomIdCreat() *RoomIdCreate {
	workerid := rand.Int63n(1024)
	if workerid > MaxId || workerid < 0 {
		workerid = 0
	}
	return &RoomIdCreate{
		LastTimestamp: -1,
		Sequence:      0,
		WorkerId:      workerid,
	}
}
func (r *RoomIdCreate) nextId() int64 {
	r.Lock()
	defer r.Unlock()
	currentTime := time.Now().UnixMilli()
	if currentTime < r.LastTimestamp {
		log.WithField("func:", "RoomIdCreater nextId").Errorf("clock is moving backwards")
		return -1
	}
	if r.LastTimestamp == currentTime {
		r.Sequence = (r.Sequence + 1) & SequenceMask
		if r.Sequence == 0 {
			timestamp := time.Now().UnixMilli()
			for timestamp <= r.LastTimestamp {
				timestamp = time.Now().UnixMilli()
			}
			currentTime = timestamp
		}
	} else {
		r.Sequence = rand.Int63n(4096)
	}
	r.LastTimestamp = currentTime
	return ((currentTime - StartTime) << TimestampLeftShiftBits) | (r.WorkerId << IdShiftBits) | r.Sequence
}

func (r *RoomIdCreate) NextRoomId() string {
	id := r.nextId()
	if id == -1 {
		return ""
	}
	return fmt.Sprintf("rtc_%d", id)
}
